package.cpath = "luaclib/?.so;3rd/lua-cjson/?.so;majiang/?.lua;"
local skynet = require "skynet"
local queue = require "skynet.queue"
local packdeal = require "packdeal"
local send_package = packdeal.send_package
local unpack_package = packdeal.unpack_package

require "config_redis"
local NetCmd = require "common/NetCmd"
local ErrNo = require "common/ErrNo"
local Common = require "common/Common"
require "common/schema"
require "common/user_t"
local USER = require "module/user" 
local CHAT = require "module/chat"
local json   = require "cjson"

local FRIENDS = require "module/friends"  
local MAIL = require "module/mail"  
local Common = require "common/Common"

CMD = {}
POST = {}
REQUEST = {}

local watch_dog
local gate_fd
local client_fd = nil
local room_id = nil 
local room_fd = nil
local user = nil
local exit = false
local time_out_stop_room_agent = 0
local cs = queue()


-- 用户请求队列，现在是REQUEST的函数都用同一个队列
function make_queue(user,json_data,func)
    local function closure()
        func(user,json_data)
    end
    cs(closure)
end

local function destory(no_send_out)
	if no_send_out == nil then  
		skynet.send(watch_dog, "lua", "destory", user.account, user:get_uid()) 
	end
    skynet.exit()
end

-- 服务器直接踢掉玩家
function CMD.kick(address)
    skynet.call(gate_fd, "lua", "kick", client_fd)
end


-- 玩家断线处理
function CMD.close(address, no_send_out)
    if no_send_out == nil and room_fd and room_fd > 0 then
		skynet.call(room_fd, "lua", "out_line", user:get_uid() )
	end	
	destory(no_send_out) 
end

-- 玩家断线处理
function CMD.heart()
    if room_fd and room_fd > 0 then
		skynet.call(room_fd, "lua", "out_line", user:get_uid() )
	end	 
	destory() 
end

function CMD.heart_inline(address)
	if room_fd and room_fd > 0 then
		skynet.call(room_fd, "lua", "in_line", user:get_uid() )
	end	
end


local  jiesan_timer_id = nil
local  jiesan_timer_time = 0
local  in_line_flag = 0
local jiesan_fun = function()
    jiesan_timer_time = jiesan_timer_time + 1 
    if jiesan_timer_time > 6 then 
        if room_fd ~= nil then
            in_line_flag = 1
            skynet.call(room_fd, "lua", "out_line", user:get_uid() )
        end  
    end
    if jiesan_timer_time > 16 then
        skynet.send(watch_dog, "lua", "close_agent", client_fd ) 
    end
end
function REQUEST.heartbeat(user, data) 
    time_out_stop_room_agent = 0
    if jiesan_timer_id then  
        if in_line_flag == 1 then
if room_fd ~= nil then
    in_line_flag = 0
    skynet.call(room_fd, "lua", "in_line", user:get_uid() )
end  
        end
        if data.rs ~= nil and data.rs == 2 then 
            jiesan_timer_time = 4
        else
            jiesan_timer_time = -99
        end 
    else  
        jiesan_timer_id = add_skynet_timer2(5,jiesan_fun)
    end  
    send_package(client_fd, {cmd=NetCmd.S2C_HEARTBEAT, uid=user:get_uid()}) 
end



function CMD.charge(address,data)
	--local affected_rows = skynet.call("MG_SAVE", "lua", "update_order_status", data)
	--if affected_rows == nil or affected_rows <= 0 then
	--	return;
	--end
	  
	local packet = { cmd = NetCmd.S2C_CHARGE, amount = 0, left = 0 }
	send_package(client_fd, packet)
end

function REQUEST.logdata(user,data)
    local id = tonumber( data.id )
    if id ~= nil and  id > 0 then
        local ret,data = skynet.call("MG_SAVE", "lua", "get_logdata", id)
        local packet = { cmd = NetCmd.S2C_LOGDATA, ret = ret}
        if ret then
            packet.logdata = json.decode(data.content)
        end
        send_package(client_fd,packet) 
    end  
end


-- 加入朋友圈
function REQUEST.friends_add(user,data) 
    if not data or not data.fid  then
        -- skynet.error("friends_add fid error")
        return
    end  
    local uid = math.floor( user:get_uid() )
    local name = user:get_name()
    local fid = math.floor(data.fid)
    local rs = FRIENDS.friends_add( uid,  fid)   

    if rs > 0 then
        local fid_arr = FRIENDS.get_fid_admin(fid) 
        local mail_to_uid = 0
        if fid_arr ~= false or str ~= nil then 
            for k,v in pairs(fid_arr) do
                mail_to_uid = v.uid
                fname = v.name
                local mails = {0,uid,mail_to_uid,3,0,name..' ID '..uid,' 申请加入朋友圈 '..fname..' '..fid,
                os.time(),'{\\"uid\\":'..uid..',\\"fid\\":'..fid..'}'}
                MAIL.save_mails(mails) 
            end 
        end  
        send_package(client_fd, {cmd=NetCmd.S2S_FRIENDS_ADD, rs=1})
    else
        send_package(client_fd, {cmd=NetCmd.S2S_FRIENDS_ADD, rs=rs}) 
    end  
end

function REQUEST.friends_del(user,data) 
    if not data or not data.fid  then
         return
    end  
    local uid = math.floor( user:get_uid() )
    local name = user:get_name()
    local fid = math.floor(data.fid)
    local rs = FRIENDS.is_uid_fid( uid,  fid)   

    if rs > 0 then
        local fid_arr = FRIENDS.get_fid_admin(fid) 
        local mail_to_uid = 0
        if fid_arr ~= false or str ~= nil then 
            for k,v in pairs(fid_arr) do
                mail_to_uid = v.uid
                fname = v.name
                local mails = {0,uid,mail_to_uid,4,0,name..' ID '..uid,' 申请退出朋友圈 '..fname..' '..fid,
                os.time(),'{\\"uid\\":'..uid..',\\"fid\\":'..fid..'}'}
                MAIL.save_mails(mails) 
            end 
        end  
        send_package(client_fd, {cmd=NetCmd.S2C_FRIENDS_DEL, rs=1})
    else
        send_package(client_fd, {cmd=NetCmd.S2C_FRIENDS_DEL, rs=rs}) 
    end  
end

--消费日志
function REQUEST.consume_log(user,data) 
    local ret,data = skynet.call("MG_SAVE", "lua", "get_consume_log", user:get_uid()) 
    send_package(client_fd, {cmd=NetCmd.S2C_CONSUME_LOG, ret=ret, data=data})
end
--购买日志
function REQUEST.buy_log(user,data) 
    local ret,data = skynet.call("MG_SAVE", "lua", "get_order_log", user:get_uid()) 
    send_package(client_fd, {cmd=NetCmd.S2C_BUY_LOG, ret=ret, data=data})
end

--得到我加入的朋友圈 列表
function REQUEST.friends_get(user,data) 
    local ok, list = FRIENDS.friends_get(user:get_uid() ) 
    if list == nil or list == false then 
        list = {}
    end
    send_package(client_fd, {cmd=NetCmd.S2C_FRIENDS_GET, list=list})
end

--获得我加入的朋友圈 消息
function REQUEST.friends_msg(user,data)  
    -- local ok, list = FRIENDS.friends_msg( 1 ) 
    local ok, list = FRIENDS.friends_msg( user:get_uid() ) 
    if ok then
        send_package(client_fd, {cmd=NetCmd.S2C_FRIENDS_MSG, list=list})
        return
    end
end

--得到大厅游戏房间 列表
function REQUEST.game_room(user,data)   
  
    local rs = {}
    local list = {}
    for k,v in pairs(rs) do 
        i = tonumber(k)
        v['rule_type'] = tonumber(v['rule_type'])
        v['player_num'] = 220 + i
        list[i] = v
    end
    if list then
        send_package(client_fd, {cmd=NetCmd.S2C_GAME_ROOM, list=list})
        return
    end
end

--得到大厅游戏房间 id
function REQUEST.game_room_id(user,data)    
	if data.room_id == nil then
        data.room_id = 0
    end
	local appstore = 0
	if data.ios_checking then 
		appstore = 1
	end
    local room_id = data.room_id
    if data.room_id == 0 then
		room_id = skynet.call("MG_SAVE", "lua", "redis_addroom", appstore)
    end 
    if room_id then
        local service = skynet.call("MG_SAVE","lua","get_service",room_id) 
		local num,_ = string.find(service, ":") 
        local ip = string.sub(service,1,num-1)
        local port = string.sub(service,1+num)
        send_package(client_fd, {cmd=NetCmd.S2C_GAME_ROOM_ID, room_id=room_id,service=service,ip=ip, port=port})
    end
	
end

--得到大厅游戏房间 ip
function REQUEST.game_room_ip(user,data)  
    local room_id = tonumber(data.room_id)
    local service = skynet.call("MG_SAVE","lua","get_service",room_id) 
    if service then
        local num,_ = string.find(service, ":") 
        local ip = string.sub(service,1,num-1)
        local port = string.sub(service,1+num)
        send_package(client_fd, {cmd=NetCmd.S2C_GAME_ROOM_IP,room_id=room_id, service=service, ip=ip, port=port})
    end
end
 
function REQUEST.pay_type(user,data)       
    local is_activity = skynet.call("MG_SAVE","lua","get_activity",user:get_uid())   
    local money = user:get_moneyall()
    local list = skynet.call("MG_SAVE","lua","get_config_gold_buy_type") 
    local list_no = skynet.call("MG_SAVE","lua","get_config_gold_buy_type_first") 
    if money > 0 then
        money = 1
    end
    if is_activity == 1 then
        list_no = skynet.call("MG_SAVE","lua","gold_buy_type_ac") 
        if money == 0 then
            list_no = skynet.call("MG_SAVE","lua","gold_buy_type_first_ac")
        end 
        money = 0
    end  
    send_package(client_fd, {cmd=NetCmd.S2C_PAY_TYPE,list=list,money=money,list_no=list_no})
end

--充值订单号
function REQUEST.pay_get(user,data)   
    if data.num ~= nil then
        local waresid = data.num
        local price = 1
          
        local is_activity = skynet.call("MG_SAVE","lua","get_activity",user:get_uid())   
        local money = user:get_moneyall()
        local rsgold_buy_type = skynet.call("MG_SAVE","lua","get_config_gold_buy_type")
         if is_activity == 1 then
            rsgold_buy_type = skynet.call("MG_SAVE","lua","gold_buy_type_ac") 
            if money == 0 then
                rsgold_buy_type = skynet.call("MG_SAVE","lua","gold_buy_type_first_ac")
            end
        else  
            if money == 0 then
                rsgold_buy_type = skynet.call("MG_SAVE","lua","get_config_gold_buy_type_first")
            end
        end 
        for k,v in pairs(rsgold_buy_type) do
            if v[1] == data.num then
                price = v[2] * 100
            end
        end 
        local packet = skynet.call("LOGIN", "lua", "get_pay_id",{ uid=user:get_uid(), waresid=waresid, price=price})  
        packet.cmd = NetCmd.S2C_PAY_GET 
        send_package(client_fd, packet )
    end
end
--游戏版本  61   
function REQUEST.get_version(user,data)    
    send_package(client_fd, {cmd=NetCmd.S2C_VERSION,uid=user:get_uid()}) 
end
--充值订单号
function REQUEST.pay_to(user,data) 
    send_package(client_fd, {cmd=NetCmd.S2C_PAY_GET,id=id}) 
end

function REQUEST.apple_trans(user, data)
	print(json.encode(data))
	local result = skynet.call("MG_SAVE", "lua", "apple_trans", user:get_uid(), data)
	local packet = {
		cmd = NetCmd.S2C_APPLE_TRANS,
		errno	= result.errno,
		msg		= result.msg
	}
	
	if result.transactions then 
		packet.transactions = result.transactions
	end
	
	send_package(client_fd,packet)
end


--得到 mail 列表
function REQUEST.mails_get(user,data)  
    local list = MAIL.mails_get( user, 1 ) 
    send_package(client_fd, {cmd=NetCmd.S2C_MAILS_GET, list=list})
end

--得到 mail 发送   recv_id 接收者uid    title 标题   content 正文
function REQUEST.mails_send(user,data)
    MAIL.mails_send( user:get_uid(),data )  
end

--得到 mail 操作
function REQUEST.mails_draw(user,data) 
    local msg,rs = MAIL.mails_draw( user,data )   
    send_package(client_fd, {cmd=NetCmd.S2C_MAILS_DRAW, msg=msg,rs=rs})
end

--得到 mail 操作
function REQUEST.mails_del(user,data)
    MAIL.mails_del( user ,data.id )   
end
--得到 mail 操作
function REQUEST.mails_num(user)
    local num = MAIL.get_mails_num( user:get_uid() )    
    send_package(client_fd, {cmd=NetCmd.S2C_MAILS_NUM, num=num })
end
 
--钻石购买麻豆
function REQUEST.buy_bean(user,data)
    local rs = 0
    local gold = user:get_gold()
    local bean = user:get_bean()
    local gold_buy = math.floor(data.gold)
    if gold_buy > user:get_gold() then
        mdg = '钻石不足'
        rs = ErrNo.NOT_GOLD
    end 
    local bean_add = gold_buy_bean['gold_'..gold_buy]
    if rs == 0 and gold_buy == nil then
        mdg = '购买类型错误'
        rs = ErrNo.NOT_BUY_TYPE
    end  
    if rs == 0 then 
    end 
    mdg = '购买成功'
    send_package(client_fd, {cmd=NetCmd.S2C_BUY_BEAN, msg=msg,rs=rs,gold=gold,bean=bean})
end

--输入 推荐 代理 ID  送房卡20
function REQUEST.agent_id(user,data)

    local agent_id = math.floor(data.agent_id)
    local rs = 0 
    local gold_buy = 0
    if agent_id ~= user:get_uid() then
        rs = skynet.call("MG_SAVE", "lua", "agent_id", user:get_uid(), agent_id) 
        if rs == 1 then 
            skynet.call("MG_SAVE", "lua", "update_gold",{ uid = user:get_uid(), card = 0, card_add = 20, card_ex = 0}, Common.OPInvite)
        end 
    end 
    load_user(user, user:get_uid())
    local gold = user:get_gold() 
    send_package(client_fd, {cmd=NetCmd.S2C_AGENT_ID, agent_id=agent_id, rs= rs,gold=gold,gold_buy=gold_buy})
end

function CMD.add_card(address, data)
	-- local add_card_num = data.card + data.card_ex
	-- local add_cards,left = USER.add_card(user, add_card_num)
	-- skynet.call("MG_SAVE", "lua", "card_log", user:get_uid(), 1, add_cards, left, Common.OPBoka)
	-- local packet = { cmd = NetCmd.S2C_ADD_CARD, add_cards = add_cards, left = left }
	-- send_package(client_fd, packet)
end
-- 房间发送过来的离开消息，若exit为true，则销毁
function POST.leave_room()
	room_id = nil 
    room_fd = nil    
    user:set_room_id(0); 
end

function POST.cost_gold(num)
	local tag, left = USER.add_gold(user, -num)
	if tag ~= 0 then 
		skynet.call("MG_SAVE", "lua", "card_log", user:get_uid(), 0, tag, left, Common.OPLOST)
	end
end


function POST.send_user_data() 
    -- 同步所有数据到客户端 

    load_user(user, user:get_uid())
    send_package(client_fd,
    {
        cmd = NetCmd.S2C_SYNC_USER_DATA,
        key = 'gold', 
        value = user:get_gold(),
    }) 
end

function CMD.reconnect(address, gate, fd)
    watch_dog = address
    gate_fd = gate
	client_fd = fd
	skynet.call(gate, "lua", "forward", fd)
    user.fd = client_fd
	
	-- 同步所有数据到客户端
    local raw_data = sync_schema(user)
    --dump_table(raw_data)
    if raw_data then
        send_package(client_fd,
        {cmd = NetCmd.S2C_LOAD_USER_DATA,
        db = raw_data,
        })
    end
end

function CMD.start(address,gate, fd, account, uid)
	watch_dog = address
    gate_fd = gate
	client_fd = fd
	skynet.call(gate, "lua", "forward", fd)

    uid = math.floor(uid)
    user = user_t:new()
    user.account = account
    user.uid = uid
    user.fd = client_fd

    local now = os.time()

    -- 从db加载user数据，返回false表示还没有用户数据，需要新建 
    if load_user(user, uid) == false then
    end

    -- 设置登入时间
    --user.last_login_time = now;
	user:set_last_login_time(now)
	--save_schema(user,nil,nil,nil)

    -- 同步所有数据到客户端
    local raw_data = sync_schema(user)
    if raw_data then
        send_package(client_fd,
        {cmd = NetCmd.S2C_LOAD_USER_DATA,
        db = raw_data,
        })
    end
	local room_id = user:get_room_id()
	if room_id > 0 then 
		REQUEST.join_room_again(user, {room_id = room_id}, 'MAJAING_HALL')
	end


    local time_out_stop_room_fun_agent = function()       -- 定时器触发 
        time_out_stop_room_agent = time_out_stop_room_agent + 1 
        if time_out_stop_room_agent >= 60 then --3600 秒后 没动作，自动解散房间
            destory()
        end
    end
    add_skynet_timer2( 100,time_out_stop_room_fun_agent)
end

skynet.start(function()
	skynet.dispatch("lua", function(_,address, command, ...)
		local f = CMD[command]
        if f then
		    skynet.ret(skynet.pack(f(address,...)))
            return
        end

        f = POST[command]
        if f then
            f(...)
        end
	end)
end)

function tell_me(msg)
    send_package(client_fd,{
        cmd = NetCmd.S2C_TELLME,
        msg = msg,
    })
end

skynet.register_protocol {
	name = "client",
	id = skynet.PTYPE_CLIENT,
    pack = function(text)
        return text,#text
    end,
    unpack = function(msg,sz)
        return skynet.tostring(msg,sz)
    end,
	dispatch = function (_, _, text, ...)
        local json_data = unpack_package(text)
        if not json_data then
            -- skynet.error(string.format("invalid json data, fd: ",client_fd))
	        --skynet.call(gate_fd, "lua", "kick", client_fd)
            return
        end

        local f = REQUEST.func_map[json_data.cmd]
        if not f then
            --skynet.error(string.format("agent invalid json cmd:%d, fd:%d", json_data.cmd, fd))
	        --skynet.call(gate_fd, "lua", "kick", client_fd)
			 -- skynet.error("agent invalid error")
            return
        end

        if f == "redirect" then
            time_out_stop_room_agent = 0
            if room_fd and room_fd > 0 then     -- 若已经进入了房间，则直接转发到房间
                skynet.send(room_fd,"client",text)
            else
                local packet = { cmd = NetCmd.S2C_MJ_ROOM_NO_EXIST, room_id = 0 }
                send_package(client_fd,packet) 
            end
            return
        end
        --f(user,json_data)
        make_queue(user,json_data,f)
	end
}

function CMD.clean_room(room_id)
	if room_id  then 
		skynet.call("MG_SAVE","lua","clean_room_redis",room_id)
	end
end


function REQUEST.create_room(user,data,hall_name)
	
	if room_id ~= nil then 
		REQUEST.join_room_again(user,data)
		print("has room_id",room_id, user:get_uid(),user:get_name())
		return 
	end
	
	local packet = { cmd = route_hall(REQUEST.create_room, hall_name), room_id = 0 }
	local tmptt = tonumber(string.sub(data.optionType,4,4))
    if data.optionType ~= nil and  tmptt ~= nil then
        local is_gps = math.floor( tmptt )
        if is_gps ~= nil and is_gps == 1 then
            if data.latitude == nil or data.longitude == nil or 
                data.latitude < 1 or data.longitude < 1 then 
                packet.errno = ErrNo.ERROR_GPS
                user:set_room_id(0)
                send_package(client_fd,packet)
                return
            end
        end
    end
	local has_gold = user:get_gold()
    local cost_gold = skynet.call("MG_SAVE", "lua", "get_config_cost_gold_conf", hall_name)
 	if has_gold < cost_gold then 
		CMD.clean_room(data.room_id)
		packet.errno = ErrNo.GOLD_NOT_ENOUGH
		send_package(client_fd,packet)
        return
	end
 	 
	local add_room_id = nil
	if data.room_id then 
		add_room_id = math.ceil(data.room_id)  
        local fd_old = skynet.call(hall_name, "lua", "get_rooms", add_room_id)
        if fd_old ~= nil then
            add_room_id = nil
        end
	end
     if add_room_id == nil or add_room_id == 0 then
        add_room_id = skynet.call("MG_SAVE", "lua", "redis_addroom",0)
    end 
 
    skynet.call("MG_SAVE", "lua", "hall_name_hset", add_room_id, hall_name)
	data.room_id = add_room_id
    room_id = add_room_id 

     local is_room = 0
    local id = 0
	local fd = nil
    while is_room == 0 or fd == nil do
        id,fd = skynet.call(hall_name, "lua", "create_room", data) 
        id,fd = skynet.call(hall_name, "lua", "join_room", room_id)
        if not id or id <= 10000 then
            is_room = 0
        else
            is_room = 1
        end
    end 

    local uid = user:get_uid()
    local name = user:get_name()
    local head = user:get_head()
    local sex = user:get_sex()
    local ip    = user:get_ip()
    local room_info = skynet.call( fd, "lua", "join", client_fd, uid, name, head, sex, ip )
    if room_info.chair_id <= 0 then
        send_package(client_fd,packet)
        return
    end
 
    room_fd = fd

    packet.room_id = room_id
    packet.room_info = room_info
	
	-- 保存room_id	
	user:set_room_id(room_id) 

	if data.fid and data.fid > 0 then  --发送朋友圈消息 
        if data.hu_type ~= nil then
            data.ruleType = data.hu_type
        end
        print(uid,data.fid)
        FRIENDS.add_msg_room( uid,data.fid,data )  
    end
    send_package(client_fd,packet,room_id,uid)
end

function REQUEST.join_room(user,data)
	if room_id ~= nil then 
        REQUEST.join_room_again(user,data)
        return 
    end
	local add_room_id = math.ceil(data.room_id)
	local hall_name = skynet.call("MG_SAVE", "lua", "hall_name_hget", add_room_id) 
	
	local packet = { cmd = route_hall(REQUEST.join_room, hall_name), room_id = 0	 }

    local has_gold = user:get_gold()
    local cost_gold = skynet.call("MG_SAVE", "lua", "get_config_cost_gold_conf", hall_name)

    if has_gold < cost_gold then  
        packet.errno = ErrNo.GOLD_NOT_ENOUGH
        send_package(client_fd,packet)
        return
    end

	local id,fd,is_gps = skynet.call(hall_name, "lua", "join_room", add_room_id)
    if not id or id < 10000 then
		packet.errno = id
        user:set_room_id(0)
        send_package(client_fd,packet)
        return
    end
    if is_gps ~= nil and is_gps == 1  then
        if data.latitude == nil or data.longitude == nil or 
            data.latitude < 1 or data.longitude < 1 then 
            packet.errno = ErrNo.ERROR_GPS
            user:set_room_id(0)
            send_package(client_fd,packet)
            return
        end
    end

	-- 加入房间的信息(uid,head,nick_name,ip)
	local uid = user:get_uid()
	local name = user:get_name()
	local head = user:get_head()
	local sex = user:get_sex()
	local ip 	= user:get_ip()
    local room_info = skynet.call( fd, "lua", "join", client_fd, uid, name, head, sex, ip )
    if room_info.index <= 0 then
        if room_info.errno then  
		    if room_info.errno == ErrNo.ROOM_NOT_EXISTS then  
                skynet.call(hall_name,"lua","destory", add_room_id)  
            end 
			packet.errno = room_info.errno
		else
			packet.errno = ErrNo.ROOM_FULL
		end
        send_package(client_fd,packet)
        return
    end
	
	--更新房间人数
	skynet.call(hall_name,"lua","room_status", id, { count = room_info.count })
	
	
    room_id = id
    room_fd = fd

    packet.room_id = room_id
    packet.room_info = room_info

	-- 保存room_id	
	user:set_room_id(room_id)	
    send_package(client_fd,packet,room_id,uid)
end

function REQUEST.web_error(fd, data)
    local text = json.encode(data)
    packdeal.writelog_error('error',text)
end

function CMD.web_is_uid_fid(address,data)
    local uid = math.floor( user:get_uid() )
    local name = user:get_name()
    local fid = math.floor(data)
    return FRIENDS.is_uid_fid( uid,  fid)   
end

function CMD.web_friends_add(address,data)
    local uid = math.floor( user:get_uid() )
    local name = user:get_name()
    local fid = math.floor(data)
    local rs = FRIENDS.friends_add( uid,  fid)   

    if rs > 0 then
        local fid_arr = FRIENDS.get_fid_admin(fid) 
        local mail_to_uid = 0
        if fid_arr ~= false or str ~= nil then 
            for k,v in pairs(fid_arr) do
                mail_to_uid = v.uid
                fname = v.name
                local mails = {0,1,mail_to_uid,3,0,'玩家'..name..' ID '..uid..' 申请加入朋友圈'..fname..' ID '..fid,'玩家'..name..' ID '..uid..' 申请加入朋友圈'..fname..' ID '..fid,
                os.time(),'{\\"uid\\":'..uid..',\\"fid\\":'..fid..'}'}
                MAIL.save_mails(mails) 
            end 
        end  
        return 1
    else
        return 2
    end  
end

function CMD.web_join_room(address,data) 
    local room_id_old = user:get_room_id()
    local add_room_id = math.ceil(data)
    if room_id_old > 0 and add_room_id == room_id_old then --已经在其他房间，先退出
        return 1 
    end
    if room_id_old > 0 then --已经在其他房间，先退出

        local hall_name = skynet.call("MG_SAVE", "lua", "hall_name_hget", room_id_old) 
        local room_fd = skynet.call(hall_name, "lua", "get_rooms", room_id_old )
        if room_fd ~= nil then 
            local rss = skynet.call(room_fd, "lua", "leave", user:get_uid(),nil  )
            if rss ~= nil and rss > 0 then 
                return 99
            end 
        end
    end

 
    local hall_name = skynet.call("MG_SAVE", "lua", "hall_name_hget", add_room_id) 
     

    local has_gold = user:get_gold()
    local cost_gold = skynet.call("MG_SAVE", "lua", "get_config_cost_gold_conf", hall_name)
    if has_gold < cost_gold then  
        return 11
    end

    local id,room_fd = skynet.call(hall_name, "lua", "join_room", add_room_id)
    if not id or id < 10000 then
        return 2
    end 

    
    -- 加入房间的信息(uid,head,nick_name,ip)
    local uid = user:get_uid()
    local name = user:get_name()
    local head = user:get_head()
    local sex = user:get_sex()
    local ip    = user:get_ip()
    local room_info = skynet.call( room_fd, "lua", "join", client_fd, uid, name, head, sex, ip )
    if room_info.index <= 0 then 
        return 3
    end 
    --更新房间人数
    skynet.call(hall_name,"lua","room_status", id, { count = room_info.count }) 
    -- 保存room_id    
    user:set_room_id(add_room_id)  

    skynet.call(room_fd, "lua", "out_line", user:get_uid() ) 
    return 1
end

-- 重新加入游戏
function REQUEST.join_room_again(user,data)

	local add_room_id = math.ceil(data.room_id) 
	
	local hall_name = skynet.call("MG_SAVE", "lua", "hall_name_hget", add_room_id)
	
    local packet = { cmd = route_hall(REQUEST.join_room_again, hall_name), room_id = 0   }
 
 
	local id,fd = skynet.call(hall_name, "lua", "join_room_again", data.room_id, user:get_uid())
	if not id or id < 10000 then
		packet.errno = id
		user:set_room_id(0)
		send_package(client_fd,packet)
		return
	end
	
	local uid = user:get_uid()
	local name = user:get_name()
	local head = user:get_head()
	local sex = user:get_sex()
	local ip 	= user:get_ip()
	local room_info,rs_jiesan = skynet.call( fd, "lua", "join_again", client_fd, uid, name, head, sex, ip)
	if room_info == nil then
		packet.errno = 3
		send_package(client_fd,packet)
		return
    end
	
	room_id = id
	room_fd = fd

	packet.room_id = room_id
	packet.room_info = room_info
	send_package(client_fd,packet,room_id,uid) 
    
    if rs_jiesan ~= nil then
        local packet_jiesan = {
            cmd = NetCmd.S2C_MJ_APPLY_JIESAN,
            index = rs_jiesan,
        } 
        send_package(client_fd,packet_jiesan,room_id,uid) 
    end
end


-- 大厅路由
function forward_hall(func, hall_name)
    return function(user, data)
        return func(user, data, hall_name)
    end
end

function route_hall(func, hall_name)
    local route_map = {
        ['MAJAING_HALL'] = {
            [REQUEST.create_room] 		= NetCmd.S2C_MJ_CREATE_ROOM,
            [REQUEST.join_room] 		= NetCmd.S2C_MJ_JOIN_ROOM,
			[REQUEST.join_room_again ] 	= NetCmd.S2C_MJ_JOIN_ROOM_AGAIN,
        },
		['YFMJ_HALL'] = {
            [REQUEST.create_room] 		= NetCmd.S2C_MJ_CREATE_ROOM,
            [REQUEST.join_room] 		= NetCmd.S2C_MJ_JOIN_ROOM,
			[REQUEST.join_room_again ] 	= NetCmd.S2C_MJ_JOIN_ROOM_AGAIN,
        },
        ['DOUNIU_HALL'] = {
            [REQUEST.create_room]       = NetCmd.S2C_DOUNIU_CREATE_ROOM,
            [REQUEST.join_room]         = NetCmd.S2C_MJ_JOIN_ROOM,
            [REQUEST.join_room_again ]  = NetCmd.S2C_MJ_JOIN_ROOM_AGAIN,
        },
    }
    local route = route_map[hall_name]
    if route and route[func] then
        return route[func]
    end
    return 0
end

REQUEST.func_map = {
    [ NetCmd.C2S_MJ_CREATE_ROOM ]      	= forward_hall(REQUEST.create_room, "MAJAING_HALL"),
    [ NetCmd.C2S_MJ_YF_CREATE_ROOM ]    = forward_hall(REQUEST.create_room, "YFMJ_HALL"), 
	[ NetCmd.C2S_DOUNIU_CREATE_ROOM ]   	= forward_hall(REQUEST.create_room, "DOUNIU_HALL"),
	
	[ NetCmd.C2S_MJ_JOIN_ROOM       ] 	= REQUEST.join_room,
	[ NetCmd.C2S_MJ_JOIN_ROOM_AGAIN ] 	= REQUEST.join_room_again,
	
	
    [ NetCmd.C2S_MAILS_SEND ]  			= REQUEST.mails_send,
    [ NetCmd.C2S_MAILS_GET ]  			= REQUEST.mails_get,
    [ NetCmd.C2S_MAILS_DRAW ] 			= REQUEST.mails_draw,
    [ NetCmd.C2S_MAILS_DEL ]            = REQUEST.mails_del,
    [ NetCmd.C2S_MAILS_NUM ]  			= REQUEST.mails_num,

    [ NetCmd.C2S_FRIENDS_ADD ]  		= REQUEST.friends_add,
    [ NetCmd.C2S_FRIENDS_GET ]  		= REQUEST.friends_get,
	[ NetCmd.C2S_FRIENDS_MSG ]  		= REQUEST.friends_msg,
    [ NetCmd.C2S_FRIENDS_DEL ]          = REQUEST.friends_del,

    [ NetCmd.C2S_GAME_ROOM ]  			= REQUEST.game_room,
    [ NetCmd.C2S_GAME_ROOM_ID ]  		= REQUEST.game_room_id,
    [ NetCmd.C2S_GAME_ROOM_IP ]     	= REQUEST.game_room_ip,

    [ NetCmd.C2S_PAY_TYPE ]      		= REQUEST.pay_type,
    [ NetCmd.C2S_PAY_GET ]              = REQUEST.pay_get, 
    [ NetCmd.C2S_VERSION ]              = REQUEST.get_version, 
    [ NetCmd.C2S_BUY_LOG ]              = REQUEST.buy_log, 
    [ NetCmd.C2S_CONSUME_LOG ]  			= REQUEST.consume_log, 

    [ NetCmd.S2C_VOICE ]                = "redirect",
    
    [ NetCmd.C2S_READY ]               	= "redirect",
    [ NetCmd.C2S_CALL_SCORE ]          	= "redirect",
    [ NetCmd.C2S_OUT_CARD ]            	= "redirect",
    [ NetCmd.C2S_PASS ]                	= "redirect",
    [ NetCmd.C2S_ROOM_CHAT ]           	= "redirect",
    [ NetCmd.C2S_LEAVE_ROOM ]          	= "redirect",
	[ NetCmd.C2S_MJ_JIESAN ]          	= "redirect",
	
    [ NetCmd.C2S_MJ_READY ]            	= "redirect",
    [ NetCmd.C2S_MJ_OUT_CARD ]         	= "redirect",
    [ NetCmd.C2S_MJ_PENG ]             	= "redirect",
    [ NetCmd.C2S_MJ_GANG ]             	= "redirect",
    [ NetCmd.C2S_MJ_CHI_CARD ]         	= "redirect",
    [ NetCmd.C2S_MJ_CHI_HU ]           	= "redirect",
    [ NetCmd.C2S_MJ_HU ]               	= "redirect",
	
	[ NetCmd.C2S_MJ_CAN_CHI_CARD ]     	= "redirect",
    [ NetCmd.C2S_MJ_LEAVE_ROOM ]       	= "redirect",
	[ NetCmd.C2S_MJ_APPLY_JIESAN ]     	= "redirect",
	[ NetCmd.C2S_MJ_TIREN ]				= "redirect",
    [ NetCmd.C2S_MJ_APPLY_JIESAN_AGREE ]= "redirect",
    [ NetCmd.C2S_DOUNIU_BANKER ]        = "redirect",
    [ NetCmd.C2S_DOUNIU_ODDS ]          =  "redirect",
    [ NetCmd.C2S_DOUNIU_GIVE_UP_HAND ]  = "redirect",
    [ NetCmd.C2S_DOUNIU_KAN_PAI ]       = "redirect",
    [ NetCmd.C2S_ZHANJI_LOG ]= "redirect",
    
    [ NetCmd.S2C_GPS_INFO ]             = "redirect",
    [ NetCmd.S2C_GPS_DISTANCE ]         = "redirect", 
    [ NetCmd.C2S_CLEAN_DATA ]           = "redirect", 
	
	[ NetCmd.C2S_LOGDATA ] 				= REQUEST.logdata,
	[ NetCmd.C2S_HEARTBEAT		]		= REQUEST.heartbeat,
    [ NetCmd.C2S_BUY_BEAN ]             = REQUEST.buy_bean, 
    [ NetCmd.C2S_AGENT_ID ]  			= REQUEST.agent_id, 
	[ NetCmd.C2S_APPLE_TRANS		]	= REQUEST.apple_trans,
    [ NetCmd.C2S_WEB_ERROR      ]       = REQUEST.web_error,
}

